// 添加加载完后的执行函数
function addLoadEvent(func) {
    var oldLoad = window.onload;
    // 判断当前onload里是否有函数需要执行
    if (typeof window.onload !== 'function') {
        // 若无，则将新函数赋给onload
        window.onload = func;
    } else {
        // 若有，先执行旧函数，再执行新函数
        oldLoad();
        func();
    }
}

// 冻结对象函数
var constantize = (obj) => {
    Object.freeze(obj);
    Object.keys(obj).forEach((key, i) => {
        if (typeof obj[key] === 'object') {
            constantize(obj[key]);
        }
    })
}

// 数据类型判断
function getType(val) {
    if (val === null) return val + "";
    if (typeof val === "object") { // 引用类型
        let valClass = Object.prototype.toString.call(val);
        //     type = valClass.split(" ")[1].split("");
        // type.pop(); // 移除末尾的 "]"
        // return type.join("").toLowerCase();
        return valClass.match(/(?<=\s)[A-z]*(?=\])/)[0].toLowerCase()
    } else { // 值类型/函数
        return typeof val;
    }
}

// 获得当前月的天数
function getMonthCountDay(year, month) {
    // 退位：下一个月的第0天，就是上一个月的最后一天
    // return new Date(year, month + 1, 0).getDate() 
    // 进位：当前月的第32天，溢出算到下一个月上，求差值
    return 32 - new Date(year, month, 32).getDate()
}

// 获得当前月初是周几
function getMonthFirstWeekDay(year, month) {
    return new Date(year, month, 1).getDay()
}
// 获得当前月末是周几
function getMonthLastWeekDay(year, month) {
    return new Date(year, month + 1, 0).getDay()
}

// 浅拷贝
var shallowCopy = function (obj) {
    // 拷贝 Object 类型: [],{}
    if (!obj || typeof obj !== 'object') return;
    // 判断用数组还是对象
    let newObj = Array.isArray(obj) ? [] : {};
    // 只拷贝自身属性，忽略继承属性
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

// 深拷贝
var deepCopy = function (obj) {
    if (!obj || typeof obj !== 'object') return;
    let newObj = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : Obj[key];
    }
    return newObj;
}

// 多个数组交集
var intersection = function (args) {
    if (args.length === 0) return [];
    if (args.length === 1) return args[0];
    return [...new Set(args.reduce((prevArr, curArr) => {
        return prevArr.filter(item => curArr.includes(item));
    }))]
}

// 11.8面试
Array.prototype.getReader = function () {
    if (!Array.isArray(this)) return new TypeError
    var that = this
    var currentIndex = 0
    return {
        read: function (arg = 1) {
            // typeof arg === "number" && arg % 1 === 0
            if (!(Number.isInteger(arg) && arg > 0)) {
                return "Error"
            }
            return currentIndex < that.length ?
                that.slice(currentIndex, currentIndex += arg) : []
        }
    }
}

// instanceof 判断构造函数的 prototype 属性是否出现在对象的原型链上
function myInstanceof(left, right) {
    let proto = Object.getPrototypeOf(left),
        prototype = right.prototype;

    while (1) {
        if (!proto) return false;
        if (proto === prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}

// 事件委托
function delegateEvent(parent, child, event) {
    parent.addEventListener(event, function (e) {
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if (target.nodeName.toLowerCase() === child) {
            console.log(target.innerHTML)
        }
    })
}

// 手写缓存函数
let memoize = (func, content) => {
    let cache = Object.create(null) // 缓存区
    content = content || this
    return (...key) => {
        if (!cache[key]) {
            cache[key] = func.apply(content, key)
        }
        return cache[key]
    }
}

// 手写 new
function objectFactory() {
    var obj = new Object(),
        Constructor = [].shift.call(arguments)
    obj.__proto__ = Constructor.prototype
    var ret = Constructor.apply(obj, arguments)
    return typeof ret === 'object' ? ret : obj
}

// 随机排序/洗牌算法
function randomSort(arr) { // 从原数组中随机抽取一个放入新数组中
    var result = []
    while (arr.length > 0) {
        var randomIndex = Math.floor(Math.random() * arr.length)
        result.push(arr[randomIndex])
        arr.splice(randomIndex, 1)
    }
    return result
}

function shuffle(arr) {
    var temp, randomIndex, len = arr.length
    for (let i = 0; i < len; i++) {
        randomIndex = Math.floor(Math.random() * (len - i)) + i // 与后面未交换的数交换
        temp = arr[randomIndex]
        arr[randomIndex] = arr[i]
        arr[i] = temp
    }
    return arr
}

// 数字添加千分位分隔符
function addThousandSeparated(n) {
    // 用正则
    // return n && n.toString().replace(/(?!^)(?=(\d{3})+\.)/g, ',')
    n = n.toString()
    var count = 0,
        res = "",
        isInteger = false
    for (let i = n.length - 1; i >= 0; i--) { // 倒序遍历
        res += n[i]
        if (n[i] === '.') { // 是否开始整数部分
            isInteger = true
        }
        if (isInteger) { // 整数部分开始，每三位添加一个分隔符
            if (count === 3 && i !== 0) {
                count = 0
                res += ','
            }
            count++
        }
    }
    return res.split('').reverse().join('') // 将字符串翻转
}



let {
    toString: ss
} = 123
// console.log(ss, String.fromCodePoint(0x20BB7), `S`.codePointAt(0), `B`.codePointAt(0), )
function Pr(n) {
    if (n > 2) {
        return Promise.resolve('n>2')
    } else {
        return Promise.reject('n<=2')
    }
}


function FibonacciTail(n, ac1 = 1, ac2 = 2) {
    if (n <= 1) {
        return ac2
    }
    return FibonacciTail(n - 1, ac2, ac1 + ac2)
}

function Fibonacci(n) {
    if (n <= 1) return 1
    return Fibonacci(n - 1) + Fibonacci(n - 2)
}
console.log(Math.round(-3.4))

var rMap = new Map()
var arr1 = [1, 2, 2, 2, 2, 4, 3]
for (var i = 0; i < arr1.length; i++) {
    if (rMap.has(arr1[i])) {
        rMap.set(arr1[i], rMap.get(arr1[i]) + 1)
    } else {
        rMap.set(arr1[i], 1)
    }
}
console.log(rMap)
console.log(typeof rMap.get(1))

var nums = [5, 7, 7, 8, 8, 8, 8, 10]
const findFirstIndex = function (arr, target) { // 查找数组中第一个目标值
    var len = arr.length,
        left = 0,
        right = len - 1;
    while (left < right) {
        var middle = (left + right - 1) >> 1;
        if (arr[middle] < target) {
            left = middle + 1;
        } else if (arr[middle] === target) {
            right = middle;
        } else {
            // arr[middle] > target
            right = middle - 1;
        }
    }
    return left;
}
const findLastIndex = function (arr, target) { // 查找数组中最后一个目标值
    var len = arr.length;
    var left = 0,
        right = len - 1;
    while (left < right) {
        var middle = (left + right + 1) >> 1; // 向上取整 不向上取会出现死循环
        if (arr[middle] > target) {
            right = middle - 1;
        } else if (arr[middle] === target) {
            left = middle;
        } else {
            // arr[middle] < target
            left = middle + 1;
        }
    }
    return left;
}
// console.log('firstPosition of 8 is : ' + findFirstIndex(nums, 8));
// console.log('lastPosition of 8 is : ' + findLastIndex(nums, 8));


function throttle(fn, wait) {
    var lastTime = null
    return function () {
        let nowTime = +new Date()
        if (nowTime - lastTime > wait || !lastTime) {
            fn()
            lastTime = nowTime
        }
    }
}
let fn = () => {
    var time = 0;
    return function () {
        console.log('throttle ing...' + +new Date)
    }
}

function debounce(fn, wait) {
    var timer = null
    return function () {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(fn(), wait)
    }
}
// setInterval(throttle(fn(), 1000), 10)
// setInterval(debounce(fn, 1000), 1000)
setTimeout(function () {
    console.log('setTimeout');
});
Promise.resolve(function () {
    console.log('resolve');
});
Pr(1).then((success) => {
    console.log(success)
}).catch(e => {
    console.log(e)
})
new Promise((resolve, reject) => {
    console.log('promise');
    resolve();
    // reject('catch')
}).then(function () {
    console.log('then');
}).catch(e => {
    console.log(e)
});

console.log('console');